package com.utils.catche;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.URL;
import java.util.*;
import java.util.concurrent.Callable;

/**
 * 基于Ehcache的缓存
 *
 * @author: dingjiejun
 * @version: 1.0
 * @date: 2017/4/19
 */
@Component("ehcacheCache")
public class EhcacheCacheProvider implements CacheSupport {

    private Cache cache;

    private CacheManager manager;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private boolean enable = false;

    private String configFile = "/ehcache-local.xml";

    private String cacheName = "localCache";

    public String getConfigFile() {
        return configFile;
    }

    @Value("${module.cache.ehcache.file:/ehcache-local.xml}")
    public void setConfigFile(String configFile) {
        this.configFile = configFile;
    }

    public String getCacheName() {
        return cacheName;
    }

    @Value("${module.cache.ehcache.cachename:localCache}")
    public void setCacheName(String cacheName) {
        this.cacheName = cacheName;
    }

    @PostConstruct
    public void init() {
        try {
            URL url = getClass().getResource(configFile);
            manager = CacheManager.create(url);
            cache = manager.getCache(cacheName);
            logger.debug("ehcache {} loaded", cacheName);
            enable = true;
        } catch (Exception ignore) {

        }
    }

    @PreDestroy
    public void destroy() {
        try {
            enable = false;
            cache.removeAll();
            manager.shutdown();
            logger.debug("shutdown ehcache {}", cacheName);
        } catch (Exception ignore) {

        }
    }

    private void check() {
        if (!enable) {
            throw new RuntimeException("ehcache not load");
        }
    }

    /**
     * 存入缓存对象
     *
     * @param key
     * @param value
     */
    @Override
    public void put(String key, Object value) {
        check();
        Element element = new Element(key, value);
        cache.put(element);
    }

    /**
     * 存入缓存对象，带过期时间（闲置时间）
     *
     * @param key
     * @param value
     * @param timeToIdle
     */
    @Override
    public void put(String key, Object value, int timeToIdle) {
        check();
        Element element = new Element(key, value, timeToIdle, 0);
        cache.put(element);
    }

    /**
     * 获取缓存对象
     *
     * @param key
     * @return
     */
    @Override
    public Object get(String key) {
        check();
        Element element = cache.get(key);
        return element == null ? null : element.getObjectValue();
    }

    /**
     * 获取缓存对象并更新过期时间
     *
     * @param key
     * @param timeToIdle
     * @return
     */
    @Override
    public Object get(String key, int timeToIdle) {
        check();
        Element element = cache.get(key);
        if (element == null) {
            return null;
        }
        element.setTimeToIdle(timeToIdle);
        return element.getObjectValue();
    }

    /**
     * 移除缓存
     *
     * @param key
     */
    @Override
    public void remove(String... keys) {
        check();
        for (String key : keys) {
            cache.remove(key);
        }
    }

    /**
     * 判断缓存是否存在
     *
     * @param key
     * @return
     */
    @Override
    public boolean hasKey(String key) {
        check();
        return cache.isKeyInCache(key);
    }

    /**
     * 在Set中添加数据
     *
     * @param key
     * @param value
     */
    @Override
    @SuppressWarnings("unchecked")
    public void putSet(String key, String... values) {
        Set<String> set = (Set<String>) get(key);
        if (set == null) {
            set = new HashSet<String>();
        }
        set.addAll(Arrays.asList(values));
        put(key, set);
    }


    /**
     * 判断value在Set中存在
     *
     * @param key
     * @param value
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public boolean isKeyInSet(String key, String... values) {
        Set<String> set = (Set<String>) get(key);
        if(set==null){
            return false;
        }
        boolean hasKey = false;
        for (String value : values) {
            hasKey = set.contains(value);
            if(hasKey){
                break;
            }
        }
        return hasKey;
    }

    /**
     * 从Set中删除值
     *
     * @param key
     * @param value
     */
    @Override
    @SuppressWarnings("unchecked")
    public void removeSetValue(String key, String... values) {
        Set<String> set = (Set<String>) get(key);
        if (set == null) {
            return;
        }
        for (String value : values) {
            set.remove(value);
        }
        put(key, set);
    }

    /**
     * 获取Set数据
     *
     * @param key
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public Set<String> getSet(String key) {
        return (Set<String>) get(key);
    }

    /**
     * 在Map中添加数据(字符串)
     * @param key
     * @param field
     * @param value
     */
    @Override
    @SuppressWarnings("unchecked")
    public void putMap(String key,String field, String value) {
        Map<String, String> maps = (Map<String, String>) get(key);
        if (maps == null) {
            maps = new HashMap<String, String>();
        }
        maps.put(field, value);
        put(key, maps);
    }

    /**
     * 获取map中的值
     *
     * @param mapKey
     * @param key
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public String getMapValue(String key, String field) {
        Map<String, String> maps = (Map<String, String>) get(key);
        if (maps == null) {
            return null;
        }
        return maps.get(field);
    }


    /**
     * 从Map中删除字段
     *
     * @param key
     * @param field
     */
    @Override
    @SuppressWarnings("unchecked")
    public void removeMapField(String key, String field) {
        Map<String, String> maps = (Map<String, String>) get(key);
        if (maps == null) {
            return;
        }
        maps.remove(field);
        put(key, maps);
    }

    private String name;

    @Value("${module.cache.ehcache.name:local}")
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public Object getNativeCache() {
        return cache;
    }

    @Override
    public ValueWrapper get(Object key) {
        Object value = get(key.toString());
        if(value==null){
            return null;
        }
        SimpleValueWrapper vw = new SimpleValueWrapper(value);
        return vw;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T get(Object key, Class<T> type) {
        Object value = get(key.toString());
        return (T)value;
    }

    @Override
    public <T> T get(Object key, Callable<T> valueLoader) {
        return null;
    }

    @Override
    public void put(Object key, Object value) {
        if(value==null){
            remove(key.toString());
        }else{
            put(key.toString(),value);
        }
    }

    @Override
    public ValueWrapper putIfAbsent(Object key, Object value) {
        if(hasKey(key.toString())){
            return get(key);
        }else{
            if(value==null){
                remove(key.toString());
                return null;
            }else{
                put(key.toString(),value);
                SimpleValueWrapper vw = new SimpleValueWrapper(value);
                return vw;
            }
        }
    }

    @Override
    public void evict(Object key) {
        remove(key.toString());
    }

    @Override
    public void clear() {
        //安全考虑不做处理
    }

}

